package cn.ug.activity.service.impl;

import cn.ug.activity.bean.GiftBean;
import cn.ug.activity.bean.GiftRecordBean;
import cn.ug.activity.bean.GiftStatisticsBean;
import cn.ug.activity.bean.MemberExchangesBean;
import cn.ug.activity.mapper.ActivityCardMapper;
import cn.ug.activity.mapper.ActivityGiftMapper;
import cn.ug.activity.mapper.ActivityGiftRecordMapper;
import cn.ug.activity.mapper.CouponMemberMapper;
import cn.ug.activity.mapper.entity.ActivityCard;
import cn.ug.activity.mapper.entity.ActivityGift;
import cn.ug.activity.mapper.entity.ActivityGiftRecord;
import cn.ug.activity.mapper.entity.CouponMember;
import cn.ug.activity.service.ActivityGiftService;
import cn.ug.bean.base.SerializeObject;
import cn.ug.bean.type.ResultType;
import cn.ug.config.RedisGlobalLock;
import cn.ug.core.SerializeObjectError;
import cn.ug.core.ensure.Ensure;
import cn.ug.enums.GoldBeanRemarkEnum;
import cn.ug.enums.OrderNOPrefixEnum;
import cn.ug.feign.MemberAccountService;
import cn.ug.feign.PayGoldBeanRecordService;
import cn.ug.pay.bean.response.MemberAccountBean;
import cn.ug.util.SerialNumberWorker;
import cn.ug.util.UF;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static cn.ug.util.ConstantUtil.NATIVE_PRI_KEY;

@Service
public class ActivityGiftServiceImpl implements ActivityGiftService {
    @Autowired
    private ActivityGiftMapper activityGiftMapper;
    @Autowired
    private ActivityCardMapper activityCardMapper;
    @Autowired
    private ActivityGiftRecordMapper activityGiftRecordMapper;
    @Autowired
    private RedisGlobalLock redisGlobalLock;
    @Autowired
    private MemberAccountService memberAccountService;
    @Autowired
    private PayGoldBeanRecordService payGoldBeanRecordService;
    @Autowired
    private CouponMemberMapper couponMemberMapper;

    @Override
    public SerializeObject limit(String memberId, int giftId) {
        ActivityGift activityGift = activityGiftMapper.findById(giftId);
        if (activityGift == null) {
            return new SerializeObjectError("00000002");
        }
        if (activityGift.getStatus() != 1) {
            return new SerializeObjectError("22000142");
        }
        if (activityGift.getBalance() < 1) {
            return new SerializeObjectError("22000142");
        }
        if (activityGift.getSingleLimit() > 0) {
            Map<String, Object> params = new HashMap<String, Object>();
            params.put("memberId", memberId);
            params.put("giftId", giftId);
            int num = activityGiftRecordMapper.count(params);
            if (num >= activityGift.getSingleLimit()) {
                return new SerializeObjectError("22000143");
            }
        }
        return new SerializeObject(ResultType.NORMAL, "00000001");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String exchange(String memberId, int giftId) {
        String key = "ActivityGiftServiceImpl:exchange:" + memberId;
        if (!redisGlobalLock.lock(key)) {
            return null;
        }
        try {
            ActivityGift activityGift = activityGiftMapper.findById(giftId);
            if (activityGift == null) {
                Ensure.that(0).isLt(1, "00000002");
            }
            if (activityGift.getStatus() != 1) {
                Ensure.that(0).isLt(1, "22000142");
            }
            if (activityGift.getBalance() < 1) {
                Ensure.that(0).isLt(1, "22000142");
            }
            if (activityGift.getSingleLimit() > 0) {
                Map<String, Object> params = new HashMap<String, Object>();
                params.put("memberId", memberId);
                params.put("giftId", giftId);
                int num = activityGiftRecordMapper.count(params);
                if (num >= activityGift.getSingleLimit()) {
                    Ensure.that(0).isLt(1, "22000143");
                }
            }
            SerializeObject<MemberAccountBean> result =  memberAccountService.findByMemberId(memberId);
            if (result == null && result.getData() == null) {
                Ensure.that(0).isLt(1, "00000005");
            }
            MemberAccountBean memberAccountBean = result.getData();
            if (memberAccountBean.getUsableBean() < activityGift.getPrice()) {
                Ensure.that(0).isLt(1, "22000144");
            }
            ActivityGiftRecord record = new ActivityGiftRecord();
            record.setOrderNO(OrderNOPrefixEnum.GE.name() + SerialNumberWorker.getInstance().nextId());
            record.setGiftId(giftId);
            record.setMemberId(memberId);
            record.setAddTime(UF.getFormatDateTime(UF.getDateTime()));
            record.setPayBeans(activityGift.getPrice());
            if (activityGift.getType() == 2) {
                ActivityCard card = activityCardMapper.findSomeoneByGiftId(giftId);
                if (card == null) {
                    Ensure.that(0).isLt(1, "22000142");
                }
                record.setCardId(card.getId());
            }
            int rows = activityGiftRecordMapper.insert(record);
            Ensure.that(rows).isLt(1, "00000005");
            rows = activityGiftMapper.decrease(giftId);
            Ensure.that(rows).isLt(1, "00000005");
            if (activityGift.getType() == 2) {
                rows = activityCardMapper.updateStatus(record.getCardId());
                Ensure.that(rows).isLt(1, "00000005");
            } else if (activityGift.getType() == 1) {
                CouponMember couponMember = new CouponMember();
                couponMember.setMemberId(memberId);
                couponMember.setAddTime(UF.getFormatDateTime(LocalDateTime.now()));
                couponMember.setCouponId(activityGift.getCouponId());
                rows = couponMemberMapper.insert(couponMember);
                Ensure.that(rows).isLt(1, "00000005");
            }
            int beans = activityGift.getPrice();
            String remark = GoldBeanRemarkEnum.EXCHANGE.getRemark();
            int type = 2;
            String sign = DigestUtils.md5Hex(beans+memberId+remark+type+NATIVE_PRI_KEY);
            SerializeObject serializeObject = payGoldBeanRecordService.presentBeans(memberId, beans, type, remark, sign);
            if (serializeObject == null || serializeObject.getCode() != ResultType.NORMAL) {
                Ensure.that(0).isLt(1, "00000005");
            }
            return record.getOrderNO();
        } finally {
            redisGlobalLock.unlock(key);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean save(ActivityGift gift, List<ActivityCard> cards) {
        if (gift != null) {
            if (gift.getType() == 2 && (cards == null || cards.size() == 0)) {
                return false;
            }
            gift.setBalance(gift.getInitNum());
            if (gift.getId() > 0) {
                activityCardMapper.deleteByGiftId(gift.getId());
                int rows = activityGiftMapper.update(gift);
                Ensure.that(rows).isLt(1, "00000005");
                if (gift.getType() == 2) {
                    for (ActivityCard card : cards) {
                        card.setGiftId(gift.getId());
                    }
                    rows = activityCardMapper.insertInBatch(cards);
                    Ensure.that(rows).isLt(1, "00000005");
                }
            } else {
                gift.setAddTime(UF.getFormatDateTime(UF.getDateTime()));
                int rows = activityGiftMapper.insert(gift);
                Ensure.that(rows).isLt(1, "00000005");
                if (gift.getType() == 2) {
                    for (ActivityCard card : cards) {
                        card.setGiftId(gift.getId());
                    }
                    rows = activityCardMapper.insertInBatch(cards);
                    Ensure.that(rows).isLt(1, "00000005");
                }
            }
            return true;
        }
        return false;
    }

    @Override
    public boolean saveAfterOnline(ActivityGift gift) {
        if (gift != null && gift.getId() > 0) {
            return activityGiftMapper.updateAfterOnline(gift) > 0 ? true : false;
        }
        return false;
    }

    @Override
    public ActivityGift getGift(int giftId) {
        if (giftId > 0) {
            return activityGiftMapper.findById(giftId);
        }
        return null;
    }

    @Override
    public boolean hot(int id, int hot) {
        if (id > 0 && (hot == 0 || hot == 1)) {
            return activityGiftMapper.hot(id, hot) > 0 ? true : false;
        }
        return false;
    }

    @Override
    public boolean updateStatus(int id, int status, String remark, String auditorId, String auditorName) {
        if (id > 0 && status > 0) {
            ActivityGift gift = new ActivityGift();
            gift.setId(id);
            gift.setStatus(status);
            if (status == 1 || status == 2) {
                gift.setShelfTime(UF.getFormatDateTime(UF.getDateTime()));
                gift.setAuditRemark(remark);
                gift.setAuditorId(auditorId);
                gift.setAuditorName(auditorName);
            } else if (status == 3) {
                gift.setUnshelfTime(UF.getFormatDateTime(UF.getDateTime()));
                gift.setReason(remark);
            }
            return activityGiftMapper.updateStatus(gift) > 0 ? true : false;
        }
        return false;
    }

    @Override
    public List<ActivityGift> query(int status, int type, String name, String startDate, String endDate, int auditStatus, String order, String sort, int offset, int size) {
        List<String> orders = Arrays.asList("balance", "price", "exchanges", "add_time", "unshelf_time", "shelf_time");
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("status", status);
        params.put("auditStatus", auditStatus);
        params.put("type", type);
        if (StringUtils.isNotBlank(name)) {
            params.put("name", name);
        }
        if (StringUtils.isNotBlank(startDate)) {
            params.put("startDate", startDate);
        }
        if (StringUtils.isNotBlank(endDate)) {
            params.put("endDate", endDate);
        }
        if (orders.contains(order)) {
            params.put("order", order);
            params.put("sort", "desc");
            if (StringUtils.equalsIgnoreCase(sort, "asc") || StringUtils.equalsIgnoreCase(sort, "desc")) {
                params.put("sort", sort);
            }
        }
        params.put("offset", offset);
        params.put("size", size);
        return activityGiftMapper.query(params);
    }

    @Override
    public int count(int status, int type, String name, String startDate, String endDate, int auditStatus) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("status", status);
        params.put("auditStatus", auditStatus);
        params.put("type", type);
        if (StringUtils.isNotBlank(name)) {
            params.put("name", name);
        }
        if (StringUtils.isNotBlank(startDate)) {
            params.put("startDate", startDate);
        }
        if (StringUtils.isNotBlank(endDate)) {
            params.put("endDate", endDate);
        }
        return activityGiftMapper.count(params);
    }

    @Override
    public List<ActivityGiftRecord> queryRecord(String memberId, int giftId, String giftName, int giftType, String startDate, String endDate, String order, String sort, int offset, int size) {
        List<String> orders = Arrays.asList("addTime", "payBeans");
        Map<String, Object> params = new HashMap<String, Object>();
        if (StringUtils.isNotBlank(memberId)) {
            params.put("memberId", memberId);
        }
        params.put("giftType", giftType);
        params.put("giftId", giftId);
        if (StringUtils.isNotBlank(giftName)) {
            params.put("giftName", giftName);
        }
        if (StringUtils.isNotBlank(startDate)) {
            params.put("startDate", startDate);
        }
        if (StringUtils.isNotBlank(endDate)) {
            params.put("endDate", endDate);
        }
        if (orders.contains(order)) {
            params.put("order", order);
            params.put("sort", "desc");
            if (StringUtils.equalsIgnoreCase(sort, "asc") || StringUtils.equalsIgnoreCase(sort, "desc")) {
                params.put("sort", sort);
            }
        }
        params.put("offset", offset);
        params.put("size", size);
        return activityGiftRecordMapper.query(params);
    }

    @Override
    public int countRecord(String memberId, int giftId, String giftName, int giftType, String startDate, String endDate) {
        Map<String, Object> params = new HashMap<String, Object>();
        if (StringUtils.isNotBlank(memberId)) {
            params.put("memberId", memberId);
        }
        params.put("giftType", giftType);
        params.put("giftId", giftId);
        if (StringUtils.isNotBlank(giftName)) {
            params.put("giftName", giftName);
        }
        if (StringUtils.isNotBlank(startDate)) {
            params.put("startDate", startDate);
        }
        if (StringUtils.isNotBlank(endDate)) {
            params.put("endDate", endDate);
        }
        return activityGiftRecordMapper.count(params);
    }

    @Override
    public List<MemberExchangesBean> queryForExchanges(String memberMobile, String memberName, String startDate, String endDate, int startNum, int endNum, String order, String sort, int offset, int size) {
        List<String> orders = Arrays.asList("exchanges", "addTime");
        Map<String, Object> params = new HashMap<String, Object>();
        if (StringUtils.isNotBlank(memberMobile)) {
            params.put("memberMobile", memberMobile);
        }
        params.put("startNum", startNum);
        params.put("endNum", endNum);
        if (StringUtils.isNotBlank(memberName)) {
            params.put("memberName", memberName);
        }
        if (StringUtils.isNotBlank(startDate)) {
            params.put("startDate", startDate);
        }
        if (StringUtils.isNotBlank(endDate)) {
            params.put("endDate", endDate);
        }
        if (orders.contains(order)) {
            params.put("order", order);
            params.put("sort", "desc");
            if (StringUtils.equalsIgnoreCase(sort, "asc") || StringUtils.equalsIgnoreCase(sort, "desc")) {
                params.put("sort", sort);
            }
        }
        params.put("offset", offset);
        params.put("size", size);
        return activityGiftRecordMapper.queryForExchanges(params);
    }

    @Override
    public int countForExchanges(String memberMobile, String memberName, String startDate, String endDate, int startNum, int endNum) {
        Map<String, Object> params = new HashMap<String, Object>();
        if (StringUtils.isNotBlank(memberMobile)) {
            params.put("memberMobile", memberMobile);
        }
        params.put("startNum", startNum);
        params.put("endNum", endNum);
        if (StringUtils.isNotBlank(memberName)) {
            params.put("memberName", memberName);
        }
        if (StringUtils.isNotBlank(startDate)) {
            params.put("startDate", startDate);
        }
        if (StringUtils.isNotBlank(endDate)) {
            params.put("endDate", endDate);
        }
        return activityGiftRecordMapper.countForExchanges(params);
    }

    @Override
    public List<GiftStatisticsBean> queryForExchanges(String giftName, int startNum, int endNum, int giftType, int status, String sort, int offset, int size) {
        Map<String, Object> params = new HashMap<String, Object>();
        if (StringUtils.isNotBlank(giftName)) {
            params.put("giftName", giftName);
        }
        params.put("startNum", startNum);
        params.put("endNum", endNum);
        params.put("giftType", giftType);
        params.put("status", status);
        params.put("sort", "desc");
        if (StringUtils.equalsIgnoreCase(sort, "asc") || StringUtils.equalsIgnoreCase(sort, "desc")) {
            params.put("sort", sort);
        }
        params.put("offset", offset);
        params.put("size", size);
        return activityGiftMapper.queryForExchanges(params);
    }

    @Override
    public int countForExchanges(String giftName, int startNum, int endNum, int giftType, int status) {
        Map<String, Object> params = new HashMap<String, Object>();
        if (StringUtils.isNotBlank(giftName)) {
            params.put("giftName", giftName);
        }
        params.put("startNum", startNum);
        params.put("endNum", endNum);
        params.put("giftType", giftType);
        params.put("status", status);
        return activityGiftMapper.countForExchanges(params);
    }

    @Override
    public List<GiftBean> queryForHotList() {
        return activityGiftMapper.queryForHotList();
    }

    @Override
    public int countForHot() {
        return activityGiftMapper.countForHot();
    }

    @Override
    public List<GiftBean> queryForAppList(int giftType, int offset, int size) {
        if (giftType > 0) {
            Map<String, Object> params = new HashMap<String, Object>();
            params.put("giftType", giftType);
            params.put("offset", offset);
            params.put("size", size);
            return activityGiftMapper.queryForAppList(params);
        }
        return null;
    }

    @Override
    public int queryForAppCount(int giftType) {
        if (giftType > 0) {
            Map<String, Object> params = new HashMap<String, Object>();
            params.put("giftType", giftType);
            return activityGiftMapper.queryForAppCount(params);
        }
        return 0;
    }

    @Override
    public GiftBean findBeanById(int id) {
        if (id > 0) {
            return activityGiftMapper.findBeanById(id);
        }
        return null;
    }

    @Override
    public List<GiftRecordBean> queryForAppList(String memberId, int offset, int size) {
        if (StringUtils.isNotBlank(memberId)) {
            Map<String, Object> params = new HashMap<String, Object>();
            params.put("memberId", memberId);
            params.put("offset", offset);
            params.put("size", size);
            return activityGiftRecordMapper.queryForAppList(params);
        }
        return null;
    }

    @Override
    public int queryForAppCount(String memberId) {
        if (StringUtils.isNotBlank(memberId)) {
            Map<String, Object> params = new HashMap<String, Object>();
            params.put("memberId", memberId);
            return activityGiftRecordMapper.queryForAppCount(params);
        }
        return 0;
    }

    @Override
    public GiftRecordBean findByOrderNO(String orderNO) {
        if (StringUtils.isNotBlank(orderNO)) {
            return activityGiftRecordMapper.findByOrderNO(orderNO);
        }
        return null;
    }
}
